import re
import json
import time
import logging
import requests
import tkinter as tk
from src.customs_api import CustomsAPI
from src.scheduler import TaskScheduler
from tkinter import ttk, messagebox, scrolledtext


class ScheduleTab:
    def __init__(self, base):
        self.base = base
        self.scheduler = TaskScheduler()

    def setup_schedule_tab(self, parent):
        """设置定时任务界面（非阻塞版本）"""
        main_frame = ttk.Frame(parent, padding=10)
        main_frame.pack(fill='both', expand=True)

        # 任务配置区域
        config_frame = ttk.LabelFrame(main_frame, text="任务配置", padding=10)
        config_frame.pack(fill='x', padx=5, pady=5)

        # 调用间隔输入
        ttk.Label(config_frame, text="调用间隔（秒）:").grid(row=0, column=0, sticky='w', padx=5, pady=5)
        self.interval_var = tk.StringVar(value="10")
        validate_cmd = (self.base.root.register(self.validate_number), '%P')
        self.interval_entry = ttk.Entry(
            config_frame,
            textvariable=self.interval_var,
            width=10,
            validate='key',
            validatecommand=validate_cmd
        )
        self.interval_entry.grid(row=0, column=1, sticky='w', padx=5, pady=5)

        # 日志保留条数设置
        ttk.Label(config_frame, text="保留最近日志条数:").grid(row=1, column=0, sticky='w', padx=5, pady=5)
        self.log_limit_var = tk.StringVar(value="20")  # 默认保留20条
        # 复用之前的数字验证方法
        self.log_limit_entry = ttk.Entry(
            config_frame,
            textvariable=self.log_limit_var,
            width=10,
            validate='key',
            validatecommand=validate_cmd  # 复用validate_number验证
        )
        self.log_limit_entry.grid(row=1, column=1, sticky='w', padx=5, pady=5)

        # 任务控制按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill='x', padx=5, pady=10)

        self.start_btn = ttk.Button(
            button_frame,
            text="启动任务",
            command=self.start_scheduled_task
        )
        self.start_btn.pack(side='left', padx=5)

        self.stop_btn = ttk.Button(
            button_frame,
            text="终止任务",
            command=self.stop_scheduled_task,
            state='disabled'
        )
        self.stop_btn.pack(side='left', padx=5)

        # 任务状态指示
        self.status_var = tk.StringVar(value="未运行")
        ttk.Label(button_frame, textvariable=self.status_var).pack(side='left', padx=20)

        # 日志显示区域
        log_frame = ttk.LabelFrame(main_frame, text="任务日志", padding=10)
        log_frame.pack(fill='both', expand=True, padx=5, pady=5)

        log_controls = ttk.Frame(log_frame)
        log_controls.pack(fill='x', pady=(0, 5))

        self.clear_log_btn = ttk.Button(
            log_controls,
            text="清除日志",
            command=self.clear_task_log
        )
        self.clear_log_btn.pack(side='right')

        self.task_log_text = scrolledtext.ScrolledText(
            log_frame,
            height=15,
            wrap=tk.WORD
        )
        self.task_log_text.pack(fill='both', expand=True)
        self.task_log_text.config(state='disabled')


    def stop_scheduled_task(self):
        """停止定时任务"""
        self.scheduler.stop()
        self.update_task_ui(state='stopped')
        self.log_task_message("定时任务已终止")

        # 添加清除日志的方法
    def clear_task_log(self):
        """清除日志文本框内容"""
        # 临时启用文本框以清空内容
        self.task_log_text.config(state='normal')
        self.task_log_text.delete('1.0', tk.END)
        self.task_log_text.config(state='disabled')
        # 可选项：记录清除日志的操作
        self.log_task_message("日志已清空")

    def validate_number(self, value):
        """验证输入是否为数字"""
        return not value or (value.isdigit() and int(value) > 0)

    def start_scheduled_task(self):
        """启动非阻塞定时任务"""
        try:
            interval_str = self.interval_var.get().strip()
            if not interval_str or not interval_str.isdigit() or int(interval_str) <= 0:
                messagebox.showerror("输入错误", "请输入有效的调用间隔（正数）")
                return

            interval = int(interval_str)

            # 启动任务（由scheduler在独立线程中执行）
            self.scheduler.start_interval_task(interval, self.execute_scheduled_job)

            # 更新UI状态（立即执行，不阻塞）
            self.update_task_ui(state='running')
            self.log_task_message(f"定时任务已启动，调用间隔：{interval}秒")

        except Exception as e:
            messagebox.showerror("错误", f"启动定时任务失败: {str(e)}")
            self.log_task_message(f"启动任务失败: {str(e)}")


    def log_task_message(self, message):
        """通过时间前缀分割日志，确保按实际日志条数保留"""
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
        log_message = f"[{timestamp}] {message}\n"

        self.task_log_text.config(state='normal')
        self.task_log_text.insert(tk.END, log_message)

        # 获取用户设置的保留条数（默认20条，至少1条）
        try:
            log_limit = int(self.log_limit_var.get().strip() or 20)
            log_limit = max(log_limit, 1)
        except (ValueError, TypeError):
            log_limit = 20

        # 关键：用正则匹配时间前缀，提取所有日志条目
        full_log = self.task_log_text.get('1.0', tk.END)
        # 正则 pattern：匹配 [YYYY-MM-DD HH:MM:SS] 格式的时间前缀
        pattern = r'\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]'
        # 分割日志为条目列表（按时间前缀分割，过滤空字符串）
        log_entries = re.split(pattern, full_log)
        log_entries = [entry.strip() for entry in log_entries if entry.strip()]

        # 实际日志条数 = 分割后的条目数（因为每个前缀对应一条日志）
        actual_count = len(log_entries)

        # 如果超过限制，只保留最后 log_limit 条
        if actual_count > log_limit:
            # 需要保留的条目索引（从末尾往前取 log_limit 条）
            start_idx = actual_count - log_limit
            # 重新拼接保留的日志（需要补回时间前缀）
            # 先提取所有时间前缀
            timestamps = re.findall(pattern, full_log)
            # 拼接：时间前缀 + 对应内容（从 start_idx 开始）
            kept_log = ""
            for i in range(start_idx, actual_count):
                kept_log += f"{timestamps[i]}{log_entries[i]}\n"
            # 清空文本框，写入保留的日志
            self.task_log_text.delete('1.0', tk.END)
            self.task_log_text.insert(tk.END, kept_log)

        self.task_log_text.see(tk.END)
        self.task_log_text.config(state='disabled')

    def update_task_ui(self, state):
        """更新任务相关UI组件状态"""
        if state == 'running':
            self.start_btn.config(state='disabled')
            self.stop_btn.config(state='normal')
            self.interval_entry.config(state='disabled')
            self.status_var.set("运行中")
        else:
            self.start_btn.config(state='normal')
            self.stop_btn.config(state='disabled')
            self.interval_entry.config(state='normal')
            self.status_var.set("未运行")


    def execute_scheduled_job(self):
        """要执行的异步任务（在非UI线程中运行）"""
        # 任务执行前通过after()更新UI（确保在主线程执行）
        self.base.root.after(0, lambda: self.status_var.set("正在执行任务..."))

        try:
            api = CustomsAPI()
            check_data = api.get_chek_data()
            if check_data and check_data != {}:
                code = "CUSTOMS" + api.check_url.split('check')[-1]
                session_id = code + str(int(time.time() * 1000))
                check_data['sessionID'] = session_id
                now_time = str(int(time.time() * 1000))
                check_sign_str = api.get_check_sign_str(now_time, check_data)
                sign = api.get_check_data_sign(now_time, check_sign_str)
                if type(sign) != str and sign.get("is_error"):
                    self.base.root.after(0, lambda: self.log_task_message(
                        f"任务执行失败: {json.dumps(sign, ensure_ascii=False)}"
                    ))
                    return
                customs179_result = api.send_179_data(sign, check_sign_str)
                if customs179_result.get('code') == "10000":
                    self.log_task_message(f"回调:{check_data.get('payExchangeInfoLists')[0].get('orderNo')}")
                    api.check_success_callback(check_data.get('payExchangeInfoLists')[0].get('orderNo'))

                # 任务成功后更新日志（通过after()确保UI线程执行）
                self.base.root.after(0, lambda: self.log_task_message(
                    f"任务执行成功: {json.dumps(customs179_result, ensure_ascii=False)}"
                ))
            else:
                self.base.root.after(0, lambda: self.log_task_message(
                    f"任务执行成功: 无需上传数据..."
                ))
        except requests.exceptions.ConnectTimeout as e:
            error_msg = f"连接超时: {str(e)}"
            self.base.root.after(0, lambda: self.log_task_message(error_msg))
            logging.warning(error_msg)
        except requests.exceptions.RequestException as e:
            error_msg = f"请求失败: {str(e)}"
            self.base.root.after(0, lambda: self.log_task_message(error_msg))
            logging.warning(error_msg)
        except Exception as e:
            error_msg = f"任务执行出错: {str(e)}"
            # 错误信息同时写入日志和弹窗（均通过UI线程）
            self.base.root.after(0, lambda: self.log_task_message(error_msg))
            self.base.root.after(0, lambda: messagebox.showerror("任务错误", error_msg))

        finally:
            # 无论成功失败，恢复状态显示
            self.base.root.after(0, lambda: self.status_var.set("运行中"))
